package cn.com.dragonsoftbravo.utils.azure;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.imageio.ImageIO;

import org.apache.log4j.Logger;

import com.microsoft.azure.storage.blob.CloudBlobDirectory;
import com.microsoft.azure.storage.blob.CloudBlockBlob;

import cn.com.dragonsoftbravo.utils.IOCloseUtils;
import cn.com.dragonsoftbravo.utils.azure.factory.BlobContainerFactory;
import cn.com.dragonsoftbravo.utils.azure.uploadwork.UploadWorker;
import cn.com.dragonsoftbravo.utils.azure.utils.ImageProcessUtils;
import cn.com.dragonsoftbravo.utils.azure.utils.MetadataUtils;

public class UploadProcess {

	private static Logger log = Logger.getLogger(UploadProcess.class);

	public static void process(String imageRef, InputStream is, int fileType, String processName, String campaignId, String extName) {

		ImageProcessUtils imageProcessUtils = new ImageProcessUtils();
		ByteArrayOutputStream os = null;
		ByteArrayOutputStream oos = null;
		ByteArrayOutputStream tos = null;
		ByteArrayOutputStream tos2 = null;

		InputStream ois = null;
		InputStream tis = null;
		InputStream tis2 = null;

		try {
			CloudBlobDirectory OriDirectory = BlobContainerFactory.getDirectoryName(campaignId, fileType);

			// The blob of original image
			CloudBlockBlob blob = OriDirectory.getBlockBlobReference(imageRef);

			// Download image to a stream
			// os = new ByteArrayOutputStream();
			// blob.download(os);
			// is = new ByteArrayInputStream(os.toByteArray());

			int originalHeight = 0;
			int originalWeight = 0;
			BufferedImage originalImage = null;

			if (fileType == 0) {
				originalImage = ImageIO.read(is);
				originalHeight = originalImage.getHeight();
				originalWeight = originalImage.getWidth();
			}

			// Upload thread pool
			ExecutorService executor = Executors.newFixedThreadPool(3);

			// Counter of 3 upload threads
			CountDownLatch signal;

			if (fileType == 0) {
				signal = new CountDownLatch(3);
			} else {
				signal = new CountDownLatch(1);
			}

			if (fileType == 0) {
				// Start to process the image1 -- original image with a water
				// mark
				log.info("Client " + processName + " : Start process image 1. Image blob name is : " + imageRef);
				oos = new ByteArrayOutputStream();
				ois = imageProcessUtils.processOriginalImage(originalImage, originalWeight, originalHeight, oos);
				log.info("Client " + processName + " : Finish process image 1. Image blob name is : " + imageRef);
			} else {
				ois = is;
			}

			// Upload the image1
			executor.execute(new UploadWorker(0, ois, blob, signal, fileType, campaignId, extName));

			if (fileType == 0) {
				// Start to process the image2 -- Cut the center part of the
				// image
				// with the 16:9 radio, and compress the image to the size of
				// 357 *
				// 201
				log.info("Client " + processName + " : Start process image 2. Image blob name is : " + imageRef);
				tos = new ByteArrayOutputStream();
				tis = imageProcessUtils.processDisplayImage(originalImage, originalWeight, originalHeight, tos);
				log.info("Client " + processName + " : Finish process image 2. Image blob name is : " + imageRef);

				// Upload the image2
				executor.execute(new UploadWorker(1, tis, blob, signal, fileType, campaignId, extName));

				// Start to process the Image3
				log.info("Client " + processName + " : Start process image 3. Image blob name is : " + imageRef);
				tos2 = new ByteArrayOutputStream();
				tis2 = imageProcessUtils.processThumbnailImage(originalImage, originalWeight, originalHeight, tos2, ois);
				log.info("Client " + processName + " : Finish process image 3. Image blob name is : " + imageRef);

				// Upload the image3
				executor.execute(new UploadWorker(2, tis2, blob, signal, fileType, campaignId, extName));
			}
			signal.await();

			MetadataUtils.setMetaData(blob, AzureConstants.METEDATA_IMAGE_STATUS, AzureConstants.IMAGE_STATUS_PENDING);
			MetadataUtils.setMetaData(blob, AzureConstants.METEDATA_IMAGE_RETURN_FLAG, AzureConstants.METEDATA_IMAGE_RETURN_FLAG);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			IOCloseUtils.close(tos2);
			IOCloseUtils.close(tos);
			IOCloseUtils.close(oos);
			IOCloseUtils.close(os);

			IOCloseUtils.close(tis2);
			IOCloseUtils.close(tis);
			IOCloseUtils.close(ois);
		}
	}

}
